<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/ir-black.min.css" crossorigin>
<style>
:root {
--highlight-color: #202;
}
html {
scrollbar-face-color: #646464;
scrollbar-base-color: #646464;
scrollbar-3dlight-color: #646464;
scrollbar-highlight-color: #646464;
scrollbar-track-color: #000;
scrollbar-arrow-color: #000;
scrollbar-shadow-color: #646464;
scrollbar-dark-shadow-color: #646464;
}
::-webkit-scrollbar { width: 14px; height: 3px;}
::-webkit-scrollbar-button {
background-color: #000;
height: 3px;}
::-webkit-scrollbar-track {
background-color: #646464;}
::-webkit-scrollbar-track-piece { background-color: #000;}
::-webkit-scrollbar-thumb { height: 50px; background-color: #666; border-radius: 7px;}
::-webkit-scrollbar-corner { background-color: #646464;}
::-webkit-resizer { background-color: #666;}
.flex {
display: flex !important;
}
body {
line-height: 1.5em;
color: #fff;
background-color: #1e1e1e;
font: 14px/1.5 Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
}
#content {
padding: 20px;
}
#sidebar {
padding: 30px;
overflow: hidden;
}
#sidebar>*:last-child {
margin-bottom: 2cm;
}
.http-server-breadcrumbs {
font-size: 130%;
margin: 0 0 15px 0;
}
#footer {
font-size: .75em;
padding: 5px 30px;
border-top: 1px solid #fff;
text-align: right;
}
#footer p {
margin: 0 0 0 1em;
display: inline-block;
}
#footer p:last-child {
margin-right: 30px;
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 300;
color: #fff;
}
h1 {
font-size: 2.5em;
line-height: 1.1em;
}
h2 {
font-size: 1.75em;
margin: 1em 0 .50em 0;
}
h3 {
font-size: 1.4em;
margin: 25px 0 10px 0;
}
h4 {
margin: 0;
font-size: 105%;
}
h1:target,
h2:target,
h3:target,
h4:target,
h5:target,
h6:target {
background: #1e1e1e;
padding: 0.2em 0;
}
a {
color: #8fd6fc;
text-decoration: none;
transition: color .3s ease-in-out;
}
a:hover {
color: #00a4fc;
}
.title code {
font-weight: bold;
}
h2[id^="header-"] {
margin-top: 2em;
}
.ident {
color: #f6fc85;
}
strong {
color: #8fd6fc;
}
pre code {
background: transparent;
font-size: .8em;
line-height: 1.4em;
}
code {
background: rgba(255, 255, 255, 0.1);
padding: 1px 4px;
overflow-wrap: break-word;
}
h1 code {
background: transparent
}
pre {
background: transparent;
border: 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
margin: 1em 0;
padding: 1ex;
}
#http-server-module-list {
display: flex;
flex-flow: column;
}
#http-server-module-list div {
display: flex;
}
#http-server-module-list dt {
min-width: 10%;
}
#http-server-module-list p {
margin-top: 0;
}
.toc ul,
#index {
list-style-type: none;
margin: 0;
padding: 0;
}
#index code {
background: transparent;
}
#index h3 {
border-bottom: 1px solid #ddd;
}
#index ul {
padding: 0;
}
#index h4 {
margin-top: .6em;
font-weight: bold;
}
/* Make TOC lists have 2+ columns when viewport is wide enough.
Assuming ~20-character identifiers and ~30% wide sidebar. */
@media (min-width: 200ex) {
#index .two-column {
column-count: 2
}
}
@media (min-width: 300ex) {
#index .two-column {
column-count: 3
}
}
dl {
margin-bottom: 2em;
}
dl dl:last-child {
margin-bottom: 4em;
}
dd {
margin: 0 0 1em 3em;
}
#header-classes+dl>dd {
margin-bottom: 3em;
}
dd dd {
margin-left: 2em;
}
dd p {
margin: 10px 0;
}
.name {
background: #000;
font-weight: bold;
font-size: .85em;
padding: 5px 10px;
display: inline-block;
min-width: 40%;
}
.name:hover {
background: #0b0b0b;
}
dt:target .name {
background: var(--highlight-color);
}
.name>span:first-child {
white-space: nowrap;
}
.name.class>span:nth-child(2) {
margin-left: .4em;
}
.inherited {
color: #999;
border-left: 5px solid #eee;
padding-left: 1em;
}
.inheritance em {
font-style: normal;
font-weight: bold;
}
.pydefname {
color: #f90;
}
/* Docstrings titles, e.g. in numpydoc format */
.desc h2 {
font-weight: 400;
font-size: 1.25em;
}
.desc h3 {
font-size: 1em;
}
.desc dt code {
background: inherit;
/* Don't grey-back parameters */
}
.source summary,
.git-link-div {
color: #666;
text-align: right;
font-weight: 400;
font-size: .8em;
text-transform: uppercase;
}
.source summary>* {
white-space: nowrap;
cursor: pointer;
}
.git-link {
color: inherit;
margin-left: 1em;
}
.source pre {
max-height: 500px;
overflow: auto;
margin: 0;
}
.source pre code {
font-size: 12px;
overflow: visible;
}
.hlist {
list-style: none;
}
.hlist li {
display: inline;
}
.hlist li:after {
content: ',\2002';
}
.hlist li:last-child:after {
content: none;
}
.hlist .hlist {
display: inline;
padding-left: 1em;
}
img {
max-width: 100%;
}
td {
padding: 0 .5em;
}
.admonition {
padding: .1em .5em;
margin-bottom: 1em;
}
.admonition-title {
font-weight: bold;
}
.admonition.note,
.admonition.info,
.admonition.important {
background: #00a;
}
.admonition.todo,
.admonition.versionadded,
.admonition.tip,
.admonition.hint {
background: #050;
}
.admonition.warning,
.admonition.versionchanged,
.admonition.deprecated {
background: #ec0;
}
.admonition.error,
.admonition.danger,
.admonition.caution {
background: #c20010;
}
p {
color: #fff;
}
</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">import sys
import os
import cv2
import time
import numpy as np
import onnx
import onnxruntime
import shutil
import src.variables as variables

# This will temporarily add the NVIDIA CUDA libraries to the system path

nvidiaPath = &#34;src/NVIDIA&#34;
nvidiaPath = os.path.join(variables.PATH, nvidiaPath)

os.environ[&#34;PATH&#34;] = nvidiaPath


# from google_drive_downloader import GoogleDriveDownloader as gdd

lane_colors = [(68,65,249),(44,114,243),(30,150,248),(74,132,249),(79,199,249),(109,190,144),(142, 144, 77),(161, 125, 39)]
log_space = np.logspace(0,2, 50, base=1/10, endpoint=True)

class LSTR():

    def __init__(self, model_type, model_path, use_gpu=True):

        # Initialize model (download if necessary)
        # models_gdrive_id = &#34;1uSyVLlZn0NDoa7RR3U6vG_OCkn0uoE8z&#34;
        # download_gdrive_tar_model(models_gdrive_id, model_type, model_path)
        self.model = self.initialize_model(model_path, use_gpu=use_gpu)

    def __call__(self, image):

        return self.detect_lanes(image)

    def initialize_model(self, model_path, use_gpu=True):

        if use_gpu:
            try:
                self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;, &#39;TensorrtExecutionProvider&#39;])
                print(&#34;ONNX Runtime with CUDA support found, using GPU&#34;)
            except:
                self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;])
                print(&#34;ONNX Runtime with CUDA support not found, using CPU instead&#34;)
        else:
            self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CPUExecutionProvider&#39;])

        # Get model info
        self.getModel_input_details()
        self.getModel_output_details()

    def detect_lanes(self, image):

        input_tensor, mask_tensor = self.prepare_inputs(image)
        
        outputs = self.inference(input_tensor, mask_tensor)

        detected_lanes, good_lanes = self.process_output(outputs)

        return detected_lanes, good_lanes

    def prepare_inputs(self, img):

        self.img_height, self.img_width, self.img_channels = img.shape

        # Transform the image for inference
        # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img,(self.input_width, self.input_height))


        # Scale input pixel values to -1 to 1
        mean=[0.485, 0.456, 0.406]
        std=[0.229, 0.224, 0.225]
        

        img = ((img/ 255.0 - mean) / std)
        # img = img/ 255.0

        img = img.transpose(2, 0, 1)
        input_tensor = img[np.newaxis,:,:,:].astype(np.float32)

        mask_tensor = np.zeros((1, 1, self.input_height, self.input_width), dtype=np.float32)
        

        return input_tensor, mask_tensor

    def inference(self, input_tensor, mask_tensor):

        outputs = self.session.run(self.output_names, {self.rgb_input_name: input_tensor, 
                                                       self.mask_input_name: mask_tensor})

        return outputs

    @staticmethod
    def softmax(x):
        &#34;&#34;&#34;Compute softmax values for each sets of scores in x.&#34;&#34;&#34;
        e_x = np.exp(x - np.max(x))
        return e_x / e_x.sum(axis=-1).T

    def process_output(self, outputs):  

        pred_logits = outputs[0]
        pred_curves = outputs[1]

        # Filter good lanes based on the probability
        prob = self.softmax(pred_logits)
        good_detections = np.where(np.argmax(prob,axis=-1)==1)
        pred_logits = pred_logits[good_detections]
        pred_curves = pred_curves[good_detections]

        lanes = []
        for lane_data in pred_curves:
            bounds = lane_data[:2]
            k_2, f_2, m_2, n_1, b_2, b_3 = lane_data[2:]

            # Calculate the points for the lane
            # Note: the logspace is used for a visual effect, np.linspace would also work as in the original repository
            y_norm = bounds[0]+log_space*(bounds[1]-bounds[0])
            x_norm = (k_2 / (y_norm - f_2) ** 2 + m_2 / (y_norm - f_2) + n_1 + b_2 * y_norm - b_3)
            lane_points = np.vstack((x_norm*self.img_width, y_norm*self.img_height)).astype(int)
            
            lanes.append(lane_points)    

        self.lanes = lanes
        self.good_lanes = good_detections[1]

        return lanes, self.good_lanes

    def getModel_input_details(self):

        model_inputs = self.session.get_inputs()
        self.rgb_input_name = self.session.get_inputs()[0].name
        self.mask_input_name = self.session.get_inputs()[1].name

        self.input_shape = self.session.get_inputs()[0].shape
        self.input_height = self.input_shape[2]
        self.input_width = self.input_shape[3]

    def getModel_output_details(self):

        model_outputs = self.session.get_outputs()
        self.output_names = [model_outputs[i].name for i in range(len(model_outputs))]
        # print(self.output_names)

    def draw_lanes(self,input_img, color=(255,191,0), fillPoly=False):

        # Write the detected line points in the image
        visualization_img = input_img.copy()

        # Draw a mask for the current lane
        right_lane = np.where(self.good_lanes==0)[0]
        left_lane = np.where(self.good_lanes==5)[0]

        if(len(left_lane) and len(right_lane)):
            
            lane_segment_img = visualization_img.copy()

            points = np.vstack((self.lanes[left_lane[0]].T,
                                np.flipud(self.lanes[right_lane[0]].T)))
            if fillPoly: cv2.fillConvexPoly(lane_segment_img, points, color=color)
            visualization_img = cv2.addWeighted(visualization_img, 0.7, lane_segment_img, 0.3, 0)
            
        for lane_num,lane_points in zip(self.good_lanes, self.lanes):
            for lane_point in lane_points.T:
                cv2.circle(visualization_img, (lane_point[0],lane_point[1]), 3, lane_colors[lane_num], -1)

        return visualization_img

# def download_gdrive_tar_model(gdrive_id, model_type, model_path):
# 
#     model_name = model_type.value
# 
#     if not os.path.exists(model_path):
#         gdd.download_file_from_google_drive(file_id=gdrive_id,
#                                     dest_path=&#39;./tmp/tmp.tar.gz&#39;)
#         tar = tarfile.open(&#34;tmp/tmp.tar.gz&#34;, &#34;r:gz&#34;)
#         tar.extractall(path=&#34;tmp/&#34;)
#         tar.close()
# 
#         shutil.move(f&#34;tmp/{model_name}/{model_name}.onnx&#34;, model_path)
#         shutil.rmtree(&#34;tmp/&#34;)

# def download_gdrive_file_model(model_path, gdrive_id):
#     if not os.path.exists(model_path):
#         gdd.download_file_from_google_drive(file_id=gdrive_id,
#                                     dest_path=model_path)

if __name__ == &#39;__main__&#39;:

    from enum import Enum
    from imread_from_url import imread_from_url

    class ModelType(Enum):
        LSTR_180X320 = &#34;lstr_180x320&#34;
        LSTR_240X320 = &#34;lstr_240x320&#34;
        LSTR_360X640 = &#34;lstr_360x640&#34;
        LSTR_480X640 = &#34;lstr_480x640&#34;
        LSTR_720X1280 = &#34;lstr_720x1280&#34;

    model_type = ModelType.LSTR_360X640
    model_path = f&#34;../models/{model_type.value}.onnx&#34;

    lane_detector = LSTR(model_type, model_path)

    img = imread_from_url(&#34;https://live.staticflickr.com/1067/1475776461_f9adc2fee9_o_d.jpg&#34;)
    detected_lanes, lane_ids = lane_detector(img)

    lane_img = lane_detector.draw_lanes(img)
    cv2.namedWindow(&#34;Detected lanes&#34;, cv2.WINDOW_NORMAL)
    cv2.imshow(&#34;Detected lanes&#34;,lane_img)
    cv2.waitKey(0)</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR"><code class="flex name class">
<span>class <span class="ident">LSTR</span></span>
<span>(</span><span>model_type, model_path, use_gpu=True)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class LSTR():

    def __init__(self, model_type, model_path, use_gpu=True):

        # Initialize model (download if necessary)
        # models_gdrive_id = &#34;1uSyVLlZn0NDoa7RR3U6vG_OCkn0uoE8z&#34;
        # download_gdrive_tar_model(models_gdrive_id, model_type, model_path)
        self.model = self.initialize_model(model_path, use_gpu=use_gpu)

    def __call__(self, image):

        return self.detect_lanes(image)

    def initialize_model(self, model_path, use_gpu=True):

        if use_gpu:
            try:
                self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;, &#39;TensorrtExecutionProvider&#39;])
                print(&#34;ONNX Runtime with CUDA support found, using GPU&#34;)
            except:
                self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;])
                print(&#34;ONNX Runtime with CUDA support not found, using CPU instead&#34;)
        else:
            self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CPUExecutionProvider&#39;])

        # Get model info
        self.getModel_input_details()
        self.getModel_output_details()

    def detect_lanes(self, image):

        input_tensor, mask_tensor = self.prepare_inputs(image)
        
        outputs = self.inference(input_tensor, mask_tensor)

        detected_lanes, good_lanes = self.process_output(outputs)

        return detected_lanes, good_lanes

    def prepare_inputs(self, img):

        self.img_height, self.img_width, self.img_channels = img.shape

        # Transform the image for inference
        # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img,(self.input_width, self.input_height))


        # Scale input pixel values to -1 to 1
        mean=[0.485, 0.456, 0.406]
        std=[0.229, 0.224, 0.225]
        

        img = ((img/ 255.0 - mean) / std)
        # img = img/ 255.0

        img = img.transpose(2, 0, 1)
        input_tensor = img[np.newaxis,:,:,:].astype(np.float32)

        mask_tensor = np.zeros((1, 1, self.input_height, self.input_width), dtype=np.float32)
        

        return input_tensor, mask_tensor

    def inference(self, input_tensor, mask_tensor):

        outputs = self.session.run(self.output_names, {self.rgb_input_name: input_tensor, 
                                                       self.mask_input_name: mask_tensor})

        return outputs

    @staticmethod
    def softmax(x):
        &#34;&#34;&#34;Compute softmax values for each sets of scores in x.&#34;&#34;&#34;
        e_x = np.exp(x - np.max(x))
        return e_x / e_x.sum(axis=-1).T

    def process_output(self, outputs):  

        pred_logits = outputs[0]
        pred_curves = outputs[1]

        # Filter good lanes based on the probability
        prob = self.softmax(pred_logits)
        good_detections = np.where(np.argmax(prob,axis=-1)==1)
        pred_logits = pred_logits[good_detections]
        pred_curves = pred_curves[good_detections]

        lanes = []
        for lane_data in pred_curves:
            bounds = lane_data[:2]
            k_2, f_2, m_2, n_1, b_2, b_3 = lane_data[2:]

            # Calculate the points for the lane
            # Note: the logspace is used for a visual effect, np.linspace would also work as in the original repository
            y_norm = bounds[0]+log_space*(bounds[1]-bounds[0])
            x_norm = (k_2 / (y_norm - f_2) ** 2 + m_2 / (y_norm - f_2) + n_1 + b_2 * y_norm - b_3)
            lane_points = np.vstack((x_norm*self.img_width, y_norm*self.img_height)).astype(int)
            
            lanes.append(lane_points)    

        self.lanes = lanes
        self.good_lanes = good_detections[1]

        return lanes, self.good_lanes

    def getModel_input_details(self):

        model_inputs = self.session.get_inputs()
        self.rgb_input_name = self.session.get_inputs()[0].name
        self.mask_input_name = self.session.get_inputs()[1].name

        self.input_shape = self.session.get_inputs()[0].shape
        self.input_height = self.input_shape[2]
        self.input_width = self.input_shape[3]

    def getModel_output_details(self):

        model_outputs = self.session.get_outputs()
        self.output_names = [model_outputs[i].name for i in range(len(model_outputs))]
        # print(self.output_names)

    def draw_lanes(self,input_img, color=(255,191,0), fillPoly=False):

        # Write the detected line points in the image
        visualization_img = input_img.copy()

        # Draw a mask for the current lane
        right_lane = np.where(self.good_lanes==0)[0]
        left_lane = np.where(self.good_lanes==5)[0]

        if(len(left_lane) and len(right_lane)):
            
            lane_segment_img = visualization_img.copy()

            points = np.vstack((self.lanes[left_lane[0]].T,
                                np.flipud(self.lanes[right_lane[0]].T)))
            if fillPoly: cv2.fillConvexPoly(lane_segment_img, points, color=color)
            visualization_img = cv2.addWeighted(visualization_img, 0.7, lane_segment_img, 0.3, 0)
            
        for lane_num,lane_points in zip(self.good_lanes, self.lanes):
            for lane_point in lane_points.T:
                cv2.circle(visualization_img, (lane_point[0],lane_point[1]), 3, lane_colors[lane_num], -1)

        return visualization_img</code></pre>
</details>
<h3>Static methods</h3>
<dl>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.softmax"><code class="name flex">
<span>def <span class="ident">softmax</span></span>(<span>x)</span>
</code></dt>
<dd>
<div class="desc"><p>Compute softmax values for each sets of scores in x.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@staticmethod
def softmax(x):
    &#34;&#34;&#34;Compute softmax values for each sets of scores in x.&#34;&#34;&#34;
    e_x = np.exp(x - np.max(x))
    return e_x / e_x.sum(axis=-1).T</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.detect_lanes"><code class="name flex">
<span>def <span class="ident">detect_lanes</span></span>(<span>self, image)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def detect_lanes(self, image):

    input_tensor, mask_tensor = self.prepare_inputs(image)
    
    outputs = self.inference(input_tensor, mask_tensor)

    detected_lanes, good_lanes = self.process_output(outputs)

    return detected_lanes, good_lanes</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.draw_lanes"><code class="name flex">
<span>def <span class="ident">draw_lanes</span></span>(<span>self, input_img, color=(255, 191, 0), fillPoly=False)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def draw_lanes(self,input_img, color=(255,191,0), fillPoly=False):

    # Write the detected line points in the image
    visualization_img = input_img.copy()

    # Draw a mask for the current lane
    right_lane = np.where(self.good_lanes==0)[0]
    left_lane = np.where(self.good_lanes==5)[0]

    if(len(left_lane) and len(right_lane)):
        
        lane_segment_img = visualization_img.copy()

        points = np.vstack((self.lanes[left_lane[0]].T,
                            np.flipud(self.lanes[right_lane[0]].T)))
        if fillPoly: cv2.fillConvexPoly(lane_segment_img, points, color=color)
        visualization_img = cv2.addWeighted(visualization_img, 0.7, lane_segment_img, 0.3, 0)
        
    for lane_num,lane_points in zip(self.good_lanes, self.lanes):
        for lane_point in lane_points.T:
            cv2.circle(visualization_img, (lane_point[0],lane_point[1]), 3, lane_colors[lane_num], -1)

    return visualization_img</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_input_details"><code class="name flex">
<span>def <span class="ident">getModel_input_details</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getModel_input_details(self):

    model_inputs = self.session.get_inputs()
    self.rgb_input_name = self.session.get_inputs()[0].name
    self.mask_input_name = self.session.get_inputs()[1].name

    self.input_shape = self.session.get_inputs()[0].shape
    self.input_height = self.input_shape[2]
    self.input_width = self.input_shape[3]</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_output_details"><code class="name flex">
<span>def <span class="ident">getModel_output_details</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def getModel_output_details(self):

    model_outputs = self.session.get_outputs()
    self.output_names = [model_outputs[i].name for i in range(len(model_outputs))]
    # print(self.output_names)</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.inference"><code class="name flex">
<span>def <span class="ident">inference</span></span>(<span>self, input_tensor, mask_tensor)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def inference(self, input_tensor, mask_tensor):

    outputs = self.session.run(self.output_names, {self.rgb_input_name: input_tensor, 
                                                   self.mask_input_name: mask_tensor})

    return outputs</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.initialize_model"><code class="name flex">
<span>def <span class="ident">initialize_model</span></span>(<span>self, model_path, use_gpu=True)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def initialize_model(self, model_path, use_gpu=True):

    if use_gpu:
        try:
            self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;, &#39;TensorrtExecutionProvider&#39;])
            print(&#34;ONNX Runtime with CUDA support found, using GPU&#34;)
        except:
            self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CUDAExecutionProvider&#39;])
            print(&#34;ONNX Runtime with CUDA support not found, using CPU instead&#34;)
    else:
        self.session = onnxruntime.InferenceSession(model_path, providers=[&#39;CPUExecutionProvider&#39;])

    # Get model info
    self.getModel_input_details()
    self.getModel_output_details()</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.prepare_inputs"><code class="name flex">
<span>def <span class="ident">prepare_inputs</span></span>(<span>self, img)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def prepare_inputs(self, img):

    self.img_height, self.img_width, self.img_channels = img.shape

    # Transform the image for inference
    # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img,(self.input_width, self.input_height))


    # Scale input pixel values to -1 to 1
    mean=[0.485, 0.456, 0.406]
    std=[0.229, 0.224, 0.225]
    

    img = ((img/ 255.0 - mean) / std)
    # img = img/ 255.0

    img = img.transpose(2, 0, 1)
    input_tensor = img[np.newaxis,:,:,:].astype(np.float32)

    mask_tensor = np.zeros((1, 1, self.input_height, self.input_width), dtype=np.float32)
    

    return input_tensor, mask_tensor</code></pre>
</details>
</dd>
<dt id="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.process_output"><code class="name flex">
<span>def <span class="ident">process_output</span></span>(<span>self, outputs)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def process_output(self, outputs):  

    pred_logits = outputs[0]
    pred_curves = outputs[1]

    # Filter good lanes based on the probability
    prob = self.softmax(pred_logits)
    good_detections = np.where(np.argmax(prob,axis=-1)==1)
    pred_logits = pred_logits[good_detections]
    pred_curves = pred_curves[good_detections]

    lanes = []
    for lane_data in pred_curves:
        bounds = lane_data[:2]
        k_2, f_2, m_2, n_1, b_2, b_3 = lane_data[2:]

        # Calculate the points for the lane
        # Note: the logspace is used for a visual effect, np.linspace would also work as in the original repository
        y_norm = bounds[0]+log_space*(bounds[1]-bounds[0])
        x_norm = (k_2 / (y_norm - f_2) ** 2 + m_2 / (y_norm - f_2) + n_1 + b_2 * y_norm - b_3)
        lane_points = np.vstack((x_norm*self.img_width, y_norm*self.img_height)).astype(int)
        
        lanes.append(lane_points)    

    self.lanes = lanes
    self.good_lanes = good_detections[1]

    return lanes, self.good_lanes</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr" href="index.html">Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR">LSTR</a></code></h4>
<ul class="">
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.detect_lanes" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.detect_lanes">detect_lanes</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.draw_lanes" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.draw_lanes">draw_lanes</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_input_details" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_input_details">getModel_input_details</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_output_details" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.getModel_output_details">getModel_output_details</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.inference" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.inference">inference</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.initialize_model" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.initialize_model">initialize_model</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.prepare_inputs" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.prepare_inputs">prepare_inputs</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.process_output" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.process_output">process_output</a></code></li>
<li><code><a title="Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.softmax" href="#Euro-Truck-Simulator-2-Lane-Assist.plugins.LSTRLaneDetection.LSTRLaneDetection.lstr.lstr.LSTR.softmax">softmax</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>